package com.yxs.go_bang.game;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yxs.go_bang.GoBangApplication;
import com.yxs.go_bang.mapper.UserMapper;
import com.yxs.go_bang.model.User;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.Resource;
import javax.annotation.Resources;
import java.io.IOException;
import java.util.UUID;

@Data
//@Component room类不是单列，不能注册成 Component
public class Room {
    private String roomId;
    private User user1;
    private User user2;
    // 先手玩家id
    private int whiteUser;

    private static final int MAX_ROW=15;
    private static final int MAX_COL=15;

    // 约定0表示未落子，初始化好的二维数组都是0
    // 使用1表示user1的落子
    // 2表示user2的落子
    private int[][] board=new int[MAX_ROW][MAX_COL];
    private ObjectMapper objectMapper=new ObjectMapper();



    private OnlineUserManaage onlineUserManaage;


    private RoomManager roomManager;

    private UserMapper userMapper;

    public Room(){
        roomId= UUID.randomUUID().toString();
        onlineUserManaage= GoBangApplication.context.getBean(OnlineUserManaage.class);
        roomManager=GoBangApplication.context.getBean(RoomManager.class);
        userMapper=GoBangApplication.context.getBean(UserMapper.class);
    }

    public void putChess(String reqJson) throws IOException {
        // 1. 记录当前落子位置
        GameRequest gameRequest=objectMapper.readValue(reqJson,GameRequest.class);
        GameResponse gameResponse=new GameResponse();
        // 记录是玩家1落的子还是玩家2落的子
        int chess=gameRequest.getUserId()==user1.getUserId()?1:2;
        int row=gameRequest.getRow();
        int col=gameRequest.getCol();
        if (board[row][col]!=0){
            // 客服端已经做过一次判断，这里增减程序健壮性
            System.out.println("当前位置："+row+" , "+col+"已经有子了");
            return;
        }
        board[row][col]=chess;
        // 打印棋盘局势，方便进行后面局势判断逻辑实现
        printBoard();
        // 进行胜负判断
        int winner=checkWinner(row,col,chess);
        // 给客服端响应,需要给所有客服端响应
        gameResponse.setMessage("putChess");
        gameResponse.setUserId(gameRequest.getUserId());
        gameResponse.setRow(row);
        gameResponse.setCol(col);
        gameResponse.setWinner(winner);

        // 需要先拿到用户的websocket session
        WebSocketSession session1 = onlineUserManaage.getFromGameRoom(user1.getUserId());
        WebSocketSession session2 = onlineUserManaage.getFromGameRoom(user2.getUserId());
        // 判空（玩家掉线）
        if (session1==null){
            // 玩家1掉线， 认为玩家2获胜
            gameResponse.setWinner(user2.getUserId());
            System.out.println("玩家1掉线，玩家2获胜");
        }
        if (session2==null){
            // 玩家2掉线，玩家1获胜
            gameResponse.setWinner(user1.getUserId());
            System.out.println("玩家2掉线，玩家1获胜");
        }
        // 把响应构造成json字符串，通过session进行传输
        String jsonResp=objectMapper.writeValueAsString(gameResponse);
        System.out.println("发送给客服端的落子响应是："+jsonResp);
        if (session1!=null){
            session1.sendMessage(new TextMessage(jsonResp));
        }
        if (session2!=null){
            session2.sendMessage(new TextMessage(jsonResp));
        }
        // 胜负已分，房间销毁
        if(gameResponse.getWinner()!=0){

            // 更新用户信息
            int winUserId=gameResponse.getWinner();
            int loseUserId=gameResponse.getWinner()==user1.getUserId()?user2.getUserId():user1.getUserId();
            userMapper.userWin(winUserId);
            userMapper.loseWin(loseUserId);

            String winName=userMapper.selectNameById(gameResponse.getWinner());
            // 游戏结束
            System.out.println("游戏结束，房间即将销毁，roomId="+roomId+" 获胜方是id name ："+ gameResponse.getWinner()+" "+winName);
            // 销毁房间
            roomManager.remove(roomId,user1.getUserId(),user2.getUserId());

        }



    }

    private void printBoard() {
        // 打印出棋盘
        System.out.println("[打印棋盘信息]"+roomId);
        System.out.println("=====================================================");
        for (int r=0;r<MAX_ROW;r++){
            for (int c = 0; c < MAX_COL; c++) {
                System.out.print(board[r][c]+" ");
            }
            System.out.println();
        }

        System.out.println("=====================================================");
    }

    private int checkWinner(int row, int col,int chess) {
        // 约定：
        // 哪个玩家获胜就返回哪个玩家的userId
        // 胜负未分返回0

        // 1. 检查所有的行
        for (int c = col-4; c <= col ; c++) {
            try{
                if (board[row][c] == chess
                && board[row][c+1]==chess
                && board[row][c+2]==chess
                && board[row][c+3]==chess
                && board[row][c+4] ==chess){
                    return chess==1?user1.getUserId():user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }
        // 2. 检查所有列
        for (int r = row-4; r <= row ; r++) {
            try{
                if (board[r][col]==chess
                && board[r+1][col]==chess
                 && board[r+2][col]==chess
                 && board[r+3][col]==chess
                 && board[r+4][col]==chess){
                    return chess==1?user1.getUserId():user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }
        // 检查左对角线
        for (int r=row-4,c=col-4;r<=row && c<=col;r++,c++){
            try {
                if (board[r][c]==chess
                && board[r+1][c+1]==chess
                && board[r+2][c+2]==chess
                && board[r+3][c+3]==chess
                && board[r+4][c+4]==chess){
                    return chess==1?user1.getUserId():user2.getUserId();

                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }
        // 检查右对角线
        for (int r=row-4,c=col+4;r<=row && c>=col;r++,c--){
            try {
                if (board[r][c]==chess
                        && board[r+1][c-1]==chess
                        && board[r+2][c-2]==chess
                        && board[r+3][c-3]==chess
                        && board[r+4][c-4]==chess){
                    return chess==1?user1.getUserId():user2.getUserId();

                }
            }catch (ArrayIndexOutOfBoundsException e){
                continue;
            }
        }
        // 胜负未分返回0
        return 0;
    }
}
